package spirit.io.nio.ifeve.selector;

import java.io.IOException;
import java.nio.channels.Channel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @author eric - 好好学习，天天向上！
 * @date 2022/1/1
 * @description
 */
public class SelectorMain {

    public void demo() {
        try {
            // 打开一个通道
            Selector selector01 = Selector.open();
            // 向Selector 注册通道
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            // 和Selector使用时配置不阻塞
            serverSocketChannel.configureBlocking(false);
            SelectionKey selectionKey = serverSocketChannel.register(selector01, SelectionKey.OP_CONNECT);

            // 获取interest
            int interest = selectionKey.interestOps();
            // 获取ready 集合
            int readySet = selectionKey.readyOps();
            // 获取channel
            Channel channel = selectionKey.channel();
            //获取selector
            Selector selector = selectionKey.selector();

            // 通过select选择通道
            selector.select();
            selector.select(100000L);
            selector.selectNow();

            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectedKeys.iterator();
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                if (key.isConnectable()) {
                    // do something...
                } else if (key.isAcceptable()) {
                    // do something...
                } else if (key.isReadable()) {
                    // do something...
                } else if (key.isWritable()) {
                    // do something...
                }
                // 注意这里需要手动移除， 否则下次有相同的事件发生，Selector 不会将其放入键集合中。
                iterator.remove();
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    Selector selector;
    ServerSocketChannel serverSocketChannel;

    public SelectorMain() {
        try {
            selector = Selector.open();
            serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.configureBlocking(false);
            // 将通道注册进Selector
            serverSocketChannel.register(selector, SelectionKey.OP_CONNECT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void listen() {
        try {
            while (true) {
                int readyChannels = selector.select();
                if (readyChannels == 0) {
                    continue;
                }
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                while (iterator.hasNext()) {
                    SelectionKey key = iterator.next();
                    if (key.isConnectable()) {
                        // do something...
                    } else if (key.isAcceptable()) {
                        // do something...
                    } else if (key.isReadable()) {
                        // do something...
                    } else if (key.isWritable()) {
                        // do something...
                    }
                    // 注意这里需要手动移除， 否则下次有相同的事件发生，Selector 不会将其放入键集合中。
                    iterator.remove();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
